#Region "Imports"
Imports System.IO
Imports System.Drawing
#End Region
''' <summary>
''' Provide methods to create image to be added to a PDF
''' </summary>
''' <remarks></remarks>
Public Class clsPDFImage
#Region "Private members"
    Private _xObject As clsPdfXObject       'The image is encapsulate in an PDF XObject
    Private _name As String                 'Unique name for the image
#End Region
#Region "Constructors"
    ''' <summary>
    ''' Create a new image to be added to a PDF
    ''' </summary>
    ''' <remarks>Only JPG images are supported, other image type will raise an exception.</remarks>
    Public Sub New(ByVal filePath As String)
        _name = GetUniqueImageName()
        _xObject = New clsPdfXObject
        _readImage(filePath)
    End Sub
    Friend Sub New(name As String, stream As clsPdfStreamObject)
        _name = name
        _xObject = New clsPdfXObject(stream)
    End Sub
#End Region
#Region "Public Properties"
    ''' <summary>
    ''' Get the image's width
    ''' </summary>
    ''' <value></value>
    ''' <returns>The width of the image, in samples</returns>
    ''' <remarks></remarks>
    Public ReadOnly Property Width() As Long
        Get
            Width = _xObject.Width
        End Get
    End Property
    ''' <summary>
    ''' Get the image's height
    ''' </summary>
    ''' <value></value>
    ''' <returns>The height of the image, in samples</returns>
    ''' <remarks></remarks>
    Public ReadOnly Property Height() As Long
        Get
            Height = _xObject.Height
        End Get
    End Property
#End Region
#Region "Public Methods"
    ''' <summary>
    ''' Save the image at the specified location
    ''' </summary>
    ''' <param name="filepath">Path with the filename to be save</param>
    ''' <remarks>Proper extension will be added automatically to filename base on image's type.
    ''' .tif for TIFF images
    ''' .jpg for JPEG images
    ''' .jp2 for JPEG 2000 images</remarks>
    Public Sub Save(filepath As String)
        Dim filterType As String

        filterType = _xObject.Dictionnary.Item(PDF_FILTER).GetString
        'We add the file extension based on filter type
        Select Case filterType
            Case PDF_CCITTFAXDECODE
                filepath += ".tif"
            Case PDF_JBIG2DECODE
                filepath += ".jpg"
            Case PDF_JPXDECODE
                filepath += ".jp2"
            Case PDF_DCTDECODE
                filepath += ".jpg"
        End Select

        Dim fs As New FileStream(filepath, FileMode.Create)
        Dim writer As New BinaryWriter(fs)
        writer.Write(_xObject.StreamObject.GetDecodedData)
        fs.Close()
    End Sub
#End Region
#Region "Friend Properties"
    ''' <summary>
    ''' Get a unique image name
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks>By giving a unique name to an image, it can be reuse anywhere in a PDF</remarks>
    Friend Function GetUniqueImageName() As String
        ImageCount += 1
        GetUniqueImageName = ImageName + "_" + ImageCount.ToString
    End Function
    ''' <summary>
    ''' Get or Set the image name
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks>Must be a unique name in the context of a PDF</remarks>
    Friend Property Name() As String
        Get
            Name = _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property
    ''' <summary>
    ''' Get the dictionnary for the image
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Friend ReadOnly Property Dictionnary() As clsPdfDictionnary
        Get
            Dictionnary = _xObject.Dictionnary
        End Get
    End Property
    ''' <summary>
    ''' Gives access to the stream object
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Friend ReadOnly Property Stream() As clsPdfStreamObject
        Get
            Stream = _xObject.StreamObject
        End Get
    End Property
    Friend ReadOnly Property IsJpeg As Boolean
        Get
            Dim filterType As String
            IsJpeg = False
            If _xObject.Dictionnary.ContainsKey(PDF_FILTER) Then
                filterType = _xObject.Dictionnary.Item(PDF_FILTER).GetString
                IsJpeg = (filterType = PDF_CCITTFAXDECODE Or filterType = PDF_JBIG2DECODE Or filterType = PDF_JPXDECODE Or filterType = PDF_DCTDECODE)
            End If
        End Get
    End Property
#End Region
#Region "Private Methods"
    Private Sub _readImage(ByVal filePath As String)
        Dim buffer(), b As Byte
        Dim imageFile As Image = Nothing

        Try
            imageFile = Drawing.Image.FromFile(filePath)
            _xObject.Width = imageFile.Size.Width
            _xObject.Height = imageFile.Size.Height
        Catch ex As Exception
            Throw New Exception("Invalid image file or file does not exist")
        End Try

        If Not imageFile.RawFormat.Equals(Drawing.Imaging.ImageFormat.Jpeg) Then
            Throw New Exception("Image format not supported")
        End If
        _xObject.StreamObject.Filter = PdfFilters.DCTDecode 'This is the filter for JPEG Image
        imageFile.Dispose()
        imageFile = Nothing


        Dim _imgRead As New BinaryReader(File.Open(filePath, FileMode.Open, FileAccess.Read))
        buffer = _imgRead.ReadBytes(2048)
        While buffer.Length > 0
            For Each b In buffer
                _xObject.AddValue(b)
            Next
            buffer = _imgRead.ReadBytes(2048)
        End While
        _imgRead.Close()
        _imgRead = Nothing
        _xObject.StreamObject.SetStreamLength()
    End Sub
#End Region
End Class
